script.

  const optionsVal = [
    {id: "channel", type: "select"},
    {id: "wipe", type: "checkbox", note: true},
    {id: "custom-tools", type: "checkbox"},
    {id: "custom-tools-adb", type: "input"},
    {id: "custom-tools-fastboot", type: "input"}
  ];

  const switchHide = (from, to) => {
    $("."+from).hide();
    $("."+to).show();
  }

  const hideAll = (id) => {
    $("."+id).hide();
  }

  const showAll = (id) => {
    $("."+id).show();
  }

  const show = (cat, id) => {
    hideAll(cat);
    $("#"+cat+"-"+id).show();
  }

  const setText = (cat, id, text) => {
    $("."+cat+"-"+id).text(text);
  }

  const getValue = (cat, id) => {
    return $("#"+cat+"-"+id).val();
  }

  const animations = {
    hideAll: () => {
      $("#particles-foreground").hide();
      $("#particles-background").hide();
      $("#push-animation").hide();
      $("#download-animation").hide();
    },
    particles: () => {
      $("#particles-foreground").show();
      $("#particles-background").show();
      $("#push-animation").hide();
      $("#download-animation").hide();
    },
    download: () => {
      $("#download-animation").show();
      $("#push-animation").hide();
      $("#particles-foreground").hide();
      $("#particles-background").hide();
    },
    push: () => {
      $("#push-animation").show();
      $("#download-animation").hide();
      $("#particles-foreground").hide();
      $("#particles-background").hide();
    }
  }

  const views = {
    hideAll: () => hideAll("views"),
    show: (id, animation) => {
      if (id != "working"){
        if (id == "done") {
          $(".ubp-robot").addClass("ubp-robot-side");
          $(".ubp-robot").removeClass("ubp-robot-foot");
        } else {
          $(".ubp-robot").removeClass("ubp-robot-side");
          $(".ubp-robot").addClass("ubp-robot-foot");
        }
        animations.hideAll();
        show("views", id);
        return;
      } else {
        $(".ubp-robot").removeClass("ubp-robot-side");
        $(".ubp-robot").removeClass("ubp-robot-foot");
        show("views", "working");
        switch (animation) {
          case "particles":
            animations.particles()
            break;
          case "download":
            animations.download()
            break;
          case "push":
            animations.push()
            break;
          default:
            animations.hideAll();
        }
      }
    }
  }

  const userText = {
    set: (id, text) => setText("user", id, text),
    remove: id => setText("user", id, "")
  }

  const header = {
    version_info: {
      set: (text) => {
        return $('#header-text').text('UBports Installer ('+text+')');
      }
    }
  }

  const footer = {
    topText: {
      set: (text) => {
        return $("#device-name").text(text)
      }
    },
    underText: {
      set: (text) => {
        return $("#device-under-text").text(text)
      }
    }
  }

  const modals = {
    bind: modal => {
      $("#btn-modal-"+modal).click(() => {
        $('#'+modal+'-modal').modal('show');
      })
    },
    show: modal => {
      $('#'+modal+'-modal').modal('show');
    },
    hide: modal => {
      $('#'+modal+'-modal').modal('hide');
    }
  }

  const getOptionVal = (option, raw) => {
    var ret = false;
    optionsVal.forEach((optionVal) => {
      if (optionVal.id === option) {
        switch (optionVal.type) {
          case "select":
            ret = raw ? $("#options-" + optionVal.id).find(":selected").val() :
                        $("#options-" + optionVal.id).find(":selected").text();
            break;
          case "checkbox":
            ret = $("#options-" + optionVal.id).is(':checked')
            if (!raw) ret = ret ? "Yes" : "No";
            break;
          default:
            ret = $("#options-" + optionVal.id).val()
            break;
        }
      }
    });
    return ret;
  }

  const optionsValToUser = () => {
    optionsVal.forEach(option => {
      userText.set(option.id, getOptionVal(option.id));
    });
  }

  const options = {
    get: getOptionVal,
    init: () => {
      $("#btn-options-close").click(() => {
        optionsValToUser();
      });
      $("#options-wipe").change(() => {
        if (getOptionVal("wipe", true)) {
          $("#options-wipe-note").show();
          switchHide("modal-install-body-no-wipe", "modal-install-body-wipe");
        } else {
          $("#options-wipe-note").hide();
          switchHide("modal-install-body-wipe", "modal-install-body-no-wipe");
        }
      });
      $("#options-custom-tools").change(() => {
        if (getOptionVal("custom-tools", true)) {
          $("#options-custom-tools-area").show();
        } else {
          $("#options-custom-tools-area").hide();
        }
      });
    },
    optionsValToUser: optionsValToUser
  }

  $("#btn-bugreport").click(() => {
    var title = $("#error-body").text();
    utils.createBugReport(title, (body) => {
      shell.openExternal("https://github.com/ubports/ubports-installer/issues/new?title="+title+"&body="+body);
    });
  });

  $("#btn-exit").click(() => {
    var window = remote.getCurrentWindow();
    window.close();
  });

  $("#help").click(() => {
    utils.createBugReport("user-requested error report", (body) => {
      shell.openExternal("https://github.com/ubports/ubports-installer/issues/new?title=please describe the problem you are experiencing&body="+body);
    });
  });

  $("#donate").click(() => {
    shell.openExternal("https://ubports.com/donate");
  });

  $("#btn-modal-select-device-unsupported").click(() => {
    modals.show('select-device');
  });

  $("#btn-modal-dev-mode").click(() => {
    modals.show('developer-mode-info');
  });

  if(utils.isSnap()) {
    $("#options-custom-tools").prop("disabled", true);
    $("#options-custom-tools-snap-note").show();
  }

  if (process.platform === "win32" && !localStorage.getItem('neverAskForWindowsDrivers')) {
    modals.show('windows-drivers');
  }

  utils.getUpdateAvailable().then((updateAvailable) => {
    if(updateAvailable) {
      utils.log.warn("This is not the latest stable release!")
      if (utils.isSnap()) {
        $("#snap-update-instructions").show();
        $("#btn-update-installer").hide();
      } else {
        $("#generic-update-instructions").show();
      }
      modals.show('new-update');
    } else {
      utils.log.debug("Running latest stable version.");
    }
  });
